// Learn TypeScript:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html

import mapUnitView from '../compoment/mapUnitView';
import { Player } from '../compoment/player';
import PlayerView from '../compoment/playerView';
import GameCtrl from '../controller/GameCtrl';
import TeMap from '../core/TeMap';
import { GameState, pInfo, PlayerInput, playerState, ServerMessage } from '../define/GameDefine';
import GameSet from '../define/GameSet';
import { PrefabKey } from '../define/PrefabKey';
import { UICommandKey } from '../define/UICommand';
import ViewMgr from '../manager/ViewMgr';
import MapModel from '../model/MapModel';
import { MapUnit } from '../object/MapUnit';
import { tool } from '../tool/UITool';
import BaseUIView from './BaseUIView';
import PositionLabelControl from '../ui/PositionLabelControl';
import { gameData } from '../tool/GameData';
import SceneMgr from '../manager/SceneMgr';
import { AudioMgr } from '../controller/AudioMgr';

const { ccclass, property } = cc._decorator;

@ccclass
export default class MapView extends BaseUIView {
  @property(cc.Node)
  eftNode: cc.Node = null;

  @property(cc.Camera)
  camera: cc.Camera = null;

  /**
   * 单个格子
   */
  @property(cc.Prefab)
  mapUnit: cc.Prefab = null;

  /**
   * 单个格子
   */
  @property(cc.Prefab)
  playerPrefab: cc.Prefab = null;

  /**
   * 格子地图
   */
  @property(cc.Node)
  map: cc.Node = null;

  // LIFE-CYCLE CALLBACKS:

  onLoad() {
    ViewMgr.ins.addEventListener(UICommandKey.gameStart, this.gameStart, this);
    ViewMgr.ins.addEventListener(UICommandKey.mapUnitChange, this.mapUnitChange, this);
  }

  start() {
    super.start();
  }

  private async gameStart() {
    this.initMap();
    this.initPlayer();
    await this.turnDark();
    await this.turnLight();
    this.followMyPlayer();
    AudioMgr.inst.playBgm('happy');
  }

  public onShow(): void {
    super.onShow();
  }

  private mapGather: any;
  private initMap(): void {
    //渲染地图
    if (!this.mapGather) {
      this.mapGather = {};

      this.renderMap();
    }
    //天启
    //this.renderWeather();
  }

  //渲染地图
  private mapItems: TeMap<cc.Node>;
  private renderMap(): void {
    let rowNum: number = GameSet.rows;
    let colNum: number = GameSet.cols;
    this.map.width = colNum * GameSet.girdWidth;
    this.map.height = rowNum * GameSet.girdHeight;
    this.map.x = 0;
    this.map.y = 0;
    let index: number = 0;
    this.mapItems = new TeMap<cc.Node>();
    for (let i: number = 0; i <rowNum; i++) {
      for (let j: number = 0; j < colNum; j++) {
        let unit: MapUnit = MapModel.ins.getData(i, j);
        let unitNode: cc.Node = tool.getPrefab(PrefabKey.MapUnit, this.mapUnit);
        unitNode.getComponent(mapUnitView).init(unit);
        this.map.addChild(unitNode);
        unitNode.x = j * GameSet.girdWidth + GameSet.girdWidth / 2;
        unitNode.y = i * GameSet.girdHeight + GameSet.girdHeight / 2;
        let key: string = `${i}_${j}`;
        this.mapItems.set(key, unitNode);
      }
    }
  }

  /**
   * 地图元素 变更
   */
  private mapUnitChange(data: any): void {
    let x: number = data.data.x;
    let y: number = data.data.y;
    let key: string = `${x}_${y}`;
    let mapNode: cc.Node = this.mapItems.get(key);
    if (mapNode) {
      mapNode.getComponent(mapUnitView).onChange();
    }
  }

  /**
   * 一开始 摄像机 追寻自己player的动画
   */
  private followMyPlayer(): void {
    let myPos: cc.Vec2 = this.myPlayerNode.position;
    cc.tween(this.camera.node)
      .to(1, { position: myPos })
      .call(() => {
        GameCtrl.inst.state = GameState.Run;
      })
      .start();
  }

  /**
   * 初始化 显示玩家
   */
  private myPlayer: Player;
  private myPlayerNode: cc.Node;
  private players: TeMap<PlayerView>; //显示所有player的节点

  @property(PositionLabelControl)
  public positionLabel: PositionLabelControl = null;

  private initPlayer(): void {
    let players: Player[] = GameCtrl.inst.players;
    this.players = new TeMap<PlayerView>();
    const nodes = [];
    for (let i: number = 0; i < players.length; i++) {
      let player: Player = players[i];
      let unitNode: cc.Node = tool.getPrefab(PrefabKey.playerPrefab, this.playerPrefab);
      nodes.push(unitNode);
      this.map.addChild(unitNode);
      unitNode.getComponent(PlayerView).init(player);
      unitNode.getComponent(PlayerView).resetPosByPosInfo(player.nowPos);
      this.players.set(player.hid, unitNode.getComponent(PlayerView));
      if (GameCtrl.inst.myRole == player.hid) {
        this.myPlayerNode = unitNode;
        this.myPlayer = player;
        // @ts-ignore
        gameData.myPlayer = player;
        this.positionLabel.initPlayerNode(unitNode);
      }
    }
    window['nodes'] = nodes;
  }

  private turnDark() {
    return new Promise((resolve, reject) => {
      cc.find('DarkView', this.node).opacity = 0;
      cc.find('DarkView', this.node).active = true;
      let action = cc.sequence(
        cc.fadeTo(1, 255).easing(cc.easeBackOut()),
        cc.callFunc(() => {
          cc.find('DarkView', this.node).opacity = 255;
          resolve(null);
        }),
      );
      cc.find('DarkView', this.node).runAction(action);
    });
  }

  private turnLight() {
    return new Promise((resolve, reject) => {
      cc.find('DarkView', this.node).active = true;
      cc.find('DarkView', this.node).opacity = 255;
      let action = cc.sequence(
        cc.fadeTo(1, 0).easing(cc.easeBackOut()),
        cc.callFunc(() => {
          cc.find('DarkView', this.node).active = false;
          cc.find('DarkView', this.node).opacity = 0;
          resolve(null);
        }),
      );
      cc.find('DarkView', this.node).runAction(action);
    });
  }

  public onHide(): void {
    super.onHide();
  }

  update(dt) {
    //镜头跟随
    if (GameCtrl.inst.state == GameState.Run) {
      if (this.myPlayer.state == playerState.Run) {
        this.camera.node.position = this.myPlayerNode.position;
        SceneMgr.inst.updatePos(this.myPlayerNode.x, this.myPlayerNode.y);
      }
    }
  }

  /**
   * 帧同步处理逻辑
   */
  public tick(infos: pInfo[] = null) {
    if (infos) {
      //录入玩家 的操作
      for (let i: number = 0; i < infos.length; i++) {
        this.runSinglePlayer(infos[i]);
      }
    }
    if (this.players) {
      //玩家操作步进
      let keys: string[] = this.players.keys;
      for (let i: number = 0; i < keys.length; i++) {
        let player: PlayerView = this.players.get(keys[i]);
        player.tick();
      }
    }
  }

  /**
   * 驱动单个玩家行为 可能为每帧执行
   */
  public runSinglePlayer(info: pInfo): void {
    let hid: string = info.hid;
    let input: number = info.input;
    let event: ServerMessage = info.eid;
    let role: PlayerView = this.players.get(hid);
    if (role) {
      role.runOrder(event, input);
    }
  }
}
